iT邦幫忙

DAY 1
1

.NET程式效能Issue系列 第 1

[Day 1][C#]Effective C# 條款一: 使用屬性代替公有欄位

  • 分享至 

  • xImage
  •  

為何要用屬性來替代公有欄位主要有下列幾項原因:
1.符合物件導向封裝概念
2.支援資料繫結
3.具修改彈性

符合物件導向封裝概念
屬性是對取得/修改內部數據的方法的一種擴展,從表面看來就像是數據成員,但內部卻是以方法實現。
在程式編譯後,編譯器在把程式編譯成MSIL時,會自動把屬性中的get區塊與set區塊編譯成兩個分離的方法。所以使用屬性能穫得函式的全部好處。

讓我們來看一下簡單的例子。假設今天有個People的類別,內含一個Name屬性,該屬性可讀可寫。

class People 
{ 
    string Name { get; set; } 
}

程式編譯後我們透過SDK內建的IL Disassembler工具查看MSIL。

我們可以發現Name屬性在MSIL中已不復可見,取而代之的是MSIL中多了兩個Method,一個是get_name、一個是set_name,這兩個方法分別對應至本來屬性的get與set區塊。

支援資料繫結
.NET中的資料繫結只支援屬性,並不支援公有欄位。這是因為資料繫結機制用反射來實作時只尋找類別的屬性。而之所以不支援公有欄位,主要是因為公有欄位把數據成員直接鋪暴露給外界較不符合物件導向的封裝原則。

具修改彈性
使用屬性在修改上也較一般公有欄位更具彈性。試想當程式中類別的公有欄位被頻繁的使用,則當我們要增加判斷防止公有欄位值為空時,我們勢必需要把散在程式中所有用到的地方都加上判斷才行。同樣的情況對於屬性來說,我們只需在屬性的get區塊增加判斷即可。

class People 
{ 
    private string _name; 
    public string Name 
    { 
        get 
        { 
            if (_name == null) 
                return string.Empty; 
            return _name; 
        } 
        set 
        { 
            _name = value; 
        } 
    } 
}

若是日後要改成多執行緒程式,使用屬性也會比使用公有欄位容易來得修改。只要在get與set區塊中加入lock即可。

class People 
{ 
    private string _name; 
    public string Name 
    { 
        get 
        { 
            lock (this) 
            { 
                if (_name == null) 
                    return string.Empty; 
                return _name; 
            } 
        } 
        set 
        { 
            lock (this) 
            { 
                _name = value; 
            } 
        } 
    } 
}

除此之外,使用屬性對於事件的增加也較為容易。

class People 
{ 
    public event EventHandler NameChanging; 
    public event EventHandler NameChanged;
    private string _name; 
    public string Name 
    { 
        get 
        { 
            if (_name == null) 
                return string.Empty; 
            return _name; 
        } 
        set 
        { 
            if (_name != value) 
            { 
                NameChanging(this, new EventArgs()); 
                _name = value; 
                NameChanged(this, new EventArgs()); 
            } 
        } 
    } 
}

注意事項
雖然屬性與公有欄位在使用上看起來是一樣的,但不代表可以先寫成公有欄位以後有需要再改成屬性,因為公有欄位與屬性所編譯出的MSIL是不同的,因此若把公有欄位改為屬性,所有使用到本來公有欄位的程式都必需重新編譯,兩者以二進制的層級來看並非是兼容的。


下一篇
[Day 2][C#]Effective C# 條款二: 運行時常數優於編譯時常數
系列文
.NET程式效能Issue11
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
pantc328
iT邦高手 1 級 ‧ 2009-10-13 19:06:33

Property 可以玩很多東西.尤其是在 Design Pattern 下.
你的屬性有一個問題.前面加 public 才比較有意義.

我最常用的Design Pattern 名稱我忘了.

public class EmployeeForm:Form{
private List<Employee> employees;
public List<Employee> Employee{
get{
if(this.employees==null)
{
//資料庫存取邏輯
}
return this.employee;
}
}
private Form_Load(object sender,EventArgs eas){
dgEmployee.ItemsSource=this.Employees;
}
}

larrynung iT邦新手 5 級 ‧ 2009-10-14 18:09:04 檢舉

謝謝您的提醒~這部分真是忽略了^^,VB.NET寫太多了。已修正,非常感謝您的意見歐。

0
TOM
iT邦新手 5 級 ‧ 2024-02-05 09:17:34

第一次看到這篇文章,很驚奇的解決我關於Null判斷的疑惑!!
但我在其他書上都沒有看到有關於null判斷的好方法(可能是我看得不夠多)
請問大大是在哪裡所學到相關.net開發相關習慣呢?

我要留言

立即登入留言